package com.hyw.supply.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hyw.supply.enums.OrderStatusEnum;
import com.hyw.supply.model.entity.SupplyOrder;
import com.hyw.supply.model.excel.SupplyOrderExcel;
import com.hyw.supply.model.query.OrderQuery;
import com.hyw.supply.model.vo.*;
import com.hyw.supply.service.SupplyOrderService;
import com.hyw.supply.utils.CharSequenceUtil;
import com.hyw.supply.utils.CustomToken;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.java.Log;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.rmi.RemoteException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

/**
 * <p>
 * 供应商订单信息 前端控制器
 * </p>
 *
 * @author zzp
 * @since 2024-04-18
 */
@RestController
@RequestMapping("/supplyOrder")
@RequiredArgsConstructor
@Tag(name = "订单列表")
@Log
public class SupplyOrderController {

    private final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");


    private final SupplyOrderService supplyOrderService;

    private final ExecutorService executorService;

    @Operation(summary = "列表查询接口")
    @PostMapping("/pageList")
    public CommonResult<PageVO<SupplyOrderVO>> pageList(@RequestBody OrderQuery orderQuery) {
        IPage<SupplyOrder> page = supplyOrderService.lambdaQuery()
                .eq(StringUtils.isNotBlank(orderQuery.getOrderNo()), SupplyOrder::getOrderNo, orderQuery.getOrderNo())
                .like(StringUtils.isNotBlank(orderQuery.getGoodsName()), SupplyOrder::getGoodsName, orderQuery.getGoodsName())
                .eq(StringUtils.isNotBlank(orderQuery.getSkuCode()), SupplyOrder::getSkuCode, orderQuery.getSkuCode())
                .eq(StringUtils.isNotBlank(orderQuery.getReceiverPhone()), SupplyOrder::getReceiverPhone, orderQuery.getReceiverPhone())
                .like(StringUtils.isNotBlank(orderQuery.getReceiver()), SupplyOrder::getReceiver, orderQuery.getReceiver())
                .eq(StringUtils.isNotBlank(orderQuery.getDeliveryMode()), SupplyOrder::getDeliveryMode, orderQuery.getDeliveryMode())
                .like(StringUtils.isNotBlank(orderQuery.getReceiverAddress()), SupplyOrder::getReceiverAddress, orderQuery.getReceiverAddress())
                .eq(StringUtils.isNotBlank(orderQuery.getSellingMode()), SupplyOrder::getSellingMode, orderQuery.getSellingMode())
                .like(StringUtils.isNotBlank(orderQuery.getRemarks()), SupplyOrder::getRemarks, orderQuery.getRemarks())
                .eq(orderQuery.getOrderStatus() != null, SupplyOrder::getOrderStatus, orderQuery.getOrderStatus())
                .apply(StringUtils.isNotBlank(orderQuery.getStartPlaceOrderDate()), "DATE(place_order_date) >= {0}", orderQuery.getStartPlaceOrderDate())
                .apply(StringUtils.isNotBlank(orderQuery.getEndPlaceOrderDate()), "DATE(place_order_date) <= {0}", orderQuery.getEndPlaceOrderDate())
                .apply(StringUtils.isNotBlank(orderQuery.getStartDeliveryDate()), "DATE(delivery_date) >= {0}", orderQuery.getStartDeliveryDate())
                .apply(StringUtils.isNotBlank(orderQuery.getEndDeliveryDate()), "DATE(delivery_date) <= {0}", orderQuery.getEndDeliveryDate())
                .like(StringUtils.isNotBlank(orderQuery.getEnterprise()), SupplyOrder::getEnterprise, orderQuery.getEnterprise())
                .eq(SupplyOrder::getCreater, CustomToken.getAccountId())
                .orderByDesc(SupplyOrder::getPlaceOrderDate).orderByDesc(SupplyOrder::getId)
                .page(orderQuery.toPage());

        PageVO<SupplyOrder> supplyItemPage = PageVO.convertPage(page);
        List<SupplyOrderVO> list = supplyItemPage.getData().stream().map(item -> {
            SupplyOrderVO supplyItem = new SupplyOrderVO();
            BeanUtils.copyProperties(item, supplyItem);
            if (item.getOrderStatus() != null) {
                supplyItem.setOrderStatus(OrderStatusEnum.getMsgByCode(item.getOrderStatus()));
                supplyItem.setOrderStatusCode(item.getOrderStatus());
            }
            supplyItem.setReceiverPhone(CharSequenceUtil.mobilePhone(supplyItem.getReceiverPhone()));
            String chinesedName = CharSequenceUtil.chineseName(supplyItem.getReceiver());
            chinesedName = chinesedName.length() > 1 ? chinesedName : chinesedName + "*";
            supplyItem.setReceiver(chinesedName);
            return supplyItem;
        }).toList();

        PageVO<SupplyOrderVO> pageVO = new PageVO<>();
        BeanUtils.copyProperties(supplyItemPage, pageVO);
        pageVO.setData(list);
        return CommonResult.success(pageVO);
    }


    @Operation(summary = "详情接口查询")
    @GetMapping("/detail/{id}")
    @Parameter(name = "id", description = "详情id", in = ParameterIn.PATH)
    public CommonResult<SupplyOrderDetailVO> pageList(@PathVariable Long id) {
        SupplyOrder supplyItem = supplyOrderService.getById(id);
        SupplyOrderDetailVO supplyItemDetailVO = new SupplyOrderDetailVO();
        BeanUtils.copyProperties(supplyItem, supplyItemDetailVO);
        if (supplyItem.getOrderStatus() != null) {
            supplyItemDetailVO.setOrderStatus(OrderStatusEnum.getMsgByCode(supplyItem.getOrderStatus()));
        }
        if (supplyItem.getOrderStatus() != null && supplyItem.getOrderStatus() <= OrderStatusEnum.SHIPPED_OUTBOUND_PART.getCode()
                && supplyItem.getDeliveryDate() != null && supplyItem.getDeliveryTime() != null) {

            if (supplyItem.getDeliveryDate().plusHours(supplyItem.getDeliveryTime()).isBefore(LocalDateTime.now())) {
                supplyItemDetailVO.setOrderStatusMessage("超出发货时效，请尽快安排发货");
            }
        }
        //获取商品信息
        GoodsInfoVO goodsInfoVO = new GoodsInfoVO();
        BeanUtils.copyProperties(supplyItem, goodsInfoVO);
        if (goodsInfoVO.getGoodsPrice() != null && goodsInfoVO.getGoodsNumber() != null) {
            goodsInfoVO.setGoodsPriceTotal(goodsInfoVO.getGoodsPrice().multiply(BigDecimal.valueOf(goodsInfoVO.getGoodsNumber())));
        }
        supplyItemDetailVO.setGoodsInfoList(List.of(goodsInfoVO));
        return CommonResult.success(supplyItemDetailVO);
    }


    @Operation(summary = "下拉框值")
    @GetMapping("/dropown")
    public CommonResult<OrderDropDownVO> dropownList() {
//        List<SupplyOrder> supplyItemList = supplyOrderService.lambdaQuery()
//                .select(SupplyOrder::getDeliveryMode, SupplyOrder::getRemarks, SupplyOrder::getReceiverAddress, SupplyOrder::getSellingMode)
//                .eq(SupplyOrder::getCreater,CustomToken.getAccountId())
//                .list();
//
//        List<DropDown> deliveryModeList = supplyItemList.stream().map(SupplyOrder::getDeliveryMode)
//                .distinct()
//                .map(item -> new DropDown(item, item)).toList();
//
//        List<DropDown> remarksList = supplyItemList.stream().map(SupplyOrder::getRemarks)
//                .distinct()
//                .map(item -> new DropDown(item, item)).toList();
//
//        List<DropDown> receiverAddressList = supplyItemList.stream().map(SupplyOrder::getReceiverAddress)
//                .distinct()
//                .map(item -> new DropDown(item, item)).toList();
//
//        List<DropDown> sellingModeList = supplyItemList.stream().map(SupplyOrder::getSellingMode)
//                .distinct()
//                .map(item -> new DropDown(item, item)).toList();
        List<DropDown> deliveryModeList = List.of(new DropDown("快递", "快递"),new DropDown("顺丰", "顺丰"),new DropDown("顺丰快递", "顺丰快递"));
        List<DropDown> sellingModeList = List.of(new DropDown("预售", "预售"));
        List<DropDown> receiverAddressList = List.of();
        List<DropDown> remarksList = List.of();
        return CommonResult.success(new OrderDropDownVO(deliveryModeList, remarksList, receiverAddressList, sellingModeList));
    }



    @Operation(summary = "导出订单")
    @PostMapping("/export")
    public void export(@RequestBody OrderQuery orderQuery, HttpServletResponse response) throws IOException {
        String accountId = CustomToken.getAccountId();
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("发货订单信息", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

        ClassPathResource classPathResource = new ClassPathResource("template/delivery-order.xlsx");
        try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream())
                .withTemplate(classPathResource.getInputStream())
                .build()) {
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
            //需要分页
            int pageSize = 1000; // 每页数据量
            int pageNum = 1; // 当前页码
            boolean hasMoreData = true; // 是否有更多数据
            String limit = "LIMIT 0" + "," + pageSize;
            while (hasMoreData) {
                List<SupplyOrderExcel> orderExcelList = processSubList(orderQuery, limit, accountId);
                if (orderExcelList.isEmpty()) {
                    hasMoreData = false;
                } else {
                    // 直接写入数据
                    excelWriter.fill(orderExcelList, writeSheet);
                    limit = "LIMIT " + (++pageNum - 1) * pageSize + "," + pageSize;
                }
            }
        } catch (IOException e) {
            throw new RemoteException("导出失败,请稍后再试！");
        }
    }




    private List<SupplyOrderExcel> processSubList(OrderQuery orderQuery, String limit, String accountId) {
        List<SupplyOrder> dataList;
        if (orderQuery.getIdList() != null && !orderQuery.getIdList().isEmpty()) {
            dataList = supplyOrderService.lambdaQuery()
                    .in(SupplyOrder::getId, orderQuery.getIdList())
                    .orderByDesc(SupplyOrder::getDeliveryDate)
                    .last(limit)
                    .list();
        } else {
            dataList = supplyOrderService.lambdaQuery()
                    .eq(StringUtils.isNotBlank(orderQuery.getOrderNo()), SupplyOrder::getOrderNo, orderQuery.getOrderNo())
                    .eq(StringUtils.isNotBlank(orderQuery.getGoodsName()), SupplyOrder::getGoodsName, orderQuery.getGoodsName())
                    .eq(StringUtils.isNotBlank(orderQuery.getSkuCode()), SupplyOrder::getSkuCode, orderQuery.getSkuCode())
                    .eq(StringUtils.isNotBlank(orderQuery.getReceiverPhone()), SupplyOrder::getReceiverPhone, orderQuery.getReceiverPhone())
                    .like(StringUtils.isNotBlank(orderQuery.getReceiver()), SupplyOrder::getReceiver, orderQuery.getReceiver())
                    .eq(StringUtils.isNotBlank(orderQuery.getDeliveryMode()), SupplyOrder::getDeliveryMode, orderQuery.getDeliveryMode())
                    .like(StringUtils.isNotBlank(orderQuery.getReceiverAddress()), SupplyOrder::getReceiverAddress, orderQuery.getReceiverAddress())
                    .eq(StringUtils.isNotBlank(orderQuery.getSellingMode()), SupplyOrder::getSellingMode, orderQuery.getSellingMode())
                    .like(StringUtils.isNotBlank(orderQuery.getRemarks()), SupplyOrder::getRemarks, orderQuery.getRemarks())
                    .eq(orderQuery.getOrderStatus() != null, SupplyOrder::getOrderStatus, orderQuery.getOrderStatus())
                    .apply(StringUtils.isNotBlank(orderQuery.getStartPlaceOrderDate()), "DATE(place_order_date) >= {0}", orderQuery.getStartPlaceOrderDate())
                    .apply(StringUtils.isNotBlank(orderQuery.getEndPlaceOrderDate()), "DATE(place_order_date) <= {0}", orderQuery.getEndPlaceOrderDate())
                    .apply(StringUtils.isNotBlank(orderQuery.getStartDeliveryDate()), "DATE(delivery_date) >= {0}", orderQuery.getStartDeliveryDate())
                    .apply(StringUtils.isNotBlank(orderQuery.getEndDeliveryDate()), "DATE(delivery_date) <= {0}", orderQuery.getEndDeliveryDate())
                    .like(StringUtils.isNotBlank(orderQuery.getEnterprise()), SupplyOrder::getEnterprise, orderQuery.getEnterprise())
                    .eq(SupplyOrder::getCreater, accountId)
                    .orderByDesc(SupplyOrder::getDeliveryDate)
                    .last(limit)
                    .list();
        }
        return getSupplyOrderExcels(dataList);

    }


    private List<SupplyOrderExcel> getSupplyOrderExcels(List<SupplyOrder> dataList) {
        return dataList.stream().map(item -> {
            SupplyOrderExcel supplyOrderExcel = new SupplyOrderExcel();
            BeanUtils.copyProperties(item, supplyOrderExcel);
            if (item.getOrderStatus() != null) {
                supplyOrderExcel.setOrderStatus(OrderStatusEnum.getMsgByCode(item.getOrderStatus()));
            }

            if (item.getPlaceOrderDate() != null) {
                supplyOrderExcel.setPlaceOrderDate(item.getPlaceOrderDate().format(timeFormatter));
            }
            if (item.getPayDate() != null) {
                supplyOrderExcel.setPayDate(item.getPayDate().format(timeFormatter));
            }
            if (item.getCompleteDate() != null) {
                supplyOrderExcel.setCompleteDate(item.getCompleteDate().format(timeFormatter));
            }
            if (item.getChoiceDate() != null) {
                supplyOrderExcel.setChoiceDate(item.getChoiceDate().format(timeFormatter));
            }
            if (item.getDeliveryDate() != null) {
                supplyOrderExcel.setDeliveryDate(item.getDeliveryDate().format(timeFormatter));
            }
            return supplyOrderExcel;
        }).toList();
    }


    @Operation(summary = "订单导入")
    @PostMapping("/import")
    @Parameter(name = "file", description = "上传文件")
    public CommonResult<?> importExcel(@RequestParam MultipartFile file) throws IOException {
        if (file == null || file.isEmpty()) {
            return CommonResult.error("请检查文件是否为空");
        }

        List<SupplyOrder> supplyOrderList = new ArrayList<>();
        EasyExcel.read(file.getInputStream(), SupplyOrderExcel.class, new PageReadListener<SupplyOrderExcel>(dataList -> {
            LocalDateTime currentDateTime = LocalDateTime.now();
            dataList.forEach(data -> {
                SupplyOrder supplyOrder = new SupplyOrder();
                BeanUtils.copyProperties(data, supplyOrder);

                supplyOrder.setOrderStatus(OrderStatusEnum.getCodeByMsg(data.getOrderStatus()));

                if (org.apache.commons.lang3.StringUtils.isNotBlank(data.getPlaceOrderDate())) {
                    supplyOrder.setPlaceOrderDate(LocalDateTime.parse(data.getPlaceOrderDate(), timeFormatter));
                }
                if (org.apache.commons.lang3.StringUtils.isNotBlank(data.getPayDate())) {
                    supplyOrder.setPayDate(LocalDateTime.parse(data.getPayDate(), timeFormatter));
                }
                if (org.apache.commons.lang3.StringUtils.isNotBlank(data.getCompleteDate())) {
                    supplyOrder.setCompleteDate(LocalDateTime.parse(data.getCompleteDate(), timeFormatter));
                }
                if (org.apache.commons.lang3.StringUtils.isNotBlank(data.getChoiceDate())) {
                    supplyOrder.setChoiceDate(LocalDateTime.parse(data.getChoiceDate(), timeFormatter));
                }
                if (org.apache.commons.lang3.StringUtils.isNotBlank(data.getDeliveryDate())) {
                    supplyOrder.setDeliveryDate(LocalDateTime.parse(data.getDeliveryDate(), timeFormatter));
                }
                supplyOrder.setCreater(Long.valueOf(CustomToken.getAccountId()));
                supplyOrder.setCreateTime(currentDateTime);
                supplyOrderList.add(supplyOrder);
            });
        })).sheet().doRead();
        if (supplyOrderList.isEmpty()) {
            return CommonResult.error("请检查文件是否为空");
        }
        supplyOrderService.saveBatch(supplyOrderList);
        return CommonResult.success("导入成功");
    }


}
